//
//  JoypadTouchControlView.m
//  iPhone SRV
//
//  Created by Nick Kitchener on 15/07/2009.
//  Copyright 2009 Nick Kitchener. All rights reserved.
//

#import "JoypadTouchControlView.h"

// Joypad use description
// Place finger in area for 2 seconds, the joypad will activate and draw an animation of centre point, maximum radius and X,Y axis with small intervals. Joypad callback
// activation event issued.
// move finger around as required, the red dot will follow under your finger. The joypad callback will be notified of the change in values.
// take finger off - the red dot will remain at the last point you touched. The joypad callback will be notified of the finger lift.
// place finger on again within 5 seconds and the dot will move to that location and follow. Again the joypad callback will be notified of the change in values.
// if the finger is taken off for longer than 5 seconds then the joypad will fade out over 5 seconds. Joypad callback deactivation event issued at the end of the time.

#define ACTIVATION_TIME 2
#define DEACTIVATION_DELAY 5
#define DEACTIVATION_TIME 5

@implementation JoypadTouchControlView
@synthesize xValue, yValue, currentState, redrawRect;

- (id)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        // Initialization code
		[self setOpaque:NO];
		[self setAlpha:0.0];
		joypadRectangle.origin.x = frame.origin.x;
		joypadRectangle.origin.y = frame.origin.y;
		joypadRectangle.size.width = frame.size.width;
		joypadRectangle.size.height = frame.size.height;
		
		currentState = [[JTCInactiveState alloc] init];
		[currentState setBroker:self];
	
		[self setNeedsDisplay];
    }
    return self;
}

- (void)dealloc {
    [super dealloc];
}

- (void)drawRect:(CGRect)rect {
    // Drawing code
	// get context
	CGContextRef context = UIGraphicsGetCurrentContext();
	
	float midX = joypadRectangle.size.width/2;
	float midY = joypadRectangle.size.height/2;
	
	CGContextClearRect(context, rect);
	
	// draw graduated circle - an outside path, then a graduated line x=0,y=0
	CGContextSetLineWidth(context, 2.0);
	CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
	
	// draw circle of joypad
	CGContextMoveToPoint(context, midX, midY);
	CGContextAddArc(context, midX, midY, midX, 0.0, 360.0, 0);
	CGContextStrokePath(context);
	
	// X=0
	CGContextMoveToPoint(context, midX, midY-midX);
	CGContextAddLineToPoint(context, midX, midY+midX);
	// Y=0
	CGContextMoveToPoint(context, 0, midY);
	CGContextAddLineToPoint(context, midX*2, midY);
	CGContextStrokePath(context);
	
	// draw current position of joypad (hopefully under the finger)
	float xPos = xValue;
	float yPos = yValue;
	CGContextAddArc(context, xPos, yPos, 10.0, 0.0, 360.0, 0);
	CGContextStrokePath(context);
	
	//CGContextRelease(context);
}

-(void)setDelegate:(id <JoypadTouchControl>)delegate {
}


-(void)setState:(JTCState *)newState {
	JTCState *o = currentState;
	
	[newState setBroker:self];
	[newState init];
	currentState = newState;
	[o release];
}

-(void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
	[currentState touchesBegan:touches withEvent:event];
}
-(void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event {
	[currentState touchesEnded:touches withEvent:event];
}
-(void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event {
	[currentState touchesMoved:touches withEvent:event];
}
-(void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event {
	[currentState touchesCancelled:touches withEvent:event];
}

- (void)activationTimerFired:(NSTimer*)theTimer {
	[currentState activationTimerFired:theTimer];
}

- (void)deactivationTimerFired:(NSTimer*)theTimer {
	[currentState deactivationTimerFired:theTimer];	
}

@end

@implementation JTCState
@synthesize broker;
-(void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event { }
-(void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event { }
-(void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event { }
-(void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event { }
- (void)activationTimerFired:(NSTimer*)theTimer { }
- (void)deactivationTimerFired:(NSTimer*)theTimer { }
@end


@implementation JTCInactiveState
@synthesize activationTimer;

-(id)init {
	if (self = [super init] ) {
		activationTimer = nil;
	}
	return self;
}

-(void) dealloc {
	if( activationTimer != nil ) {
		[activationTimer invalidate];
		[activationTimer release];
		activationTimer = nil;
	}
	[super dealloc];
}

-(void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
	NSLog(@"inactive - touches began");
	if( activationTimer == nil ) {
		activationTimer = [[NSTimer scheduledTimerWithTimeInterval:ACTIVATION_TIME
													  target:broker selector:@selector(activationTimerFired:)
												 userInfo:nil repeats:NO] retain];
	}
}

- (void)activationTimerFired:(NSTimer*)theTimer {
	NSLog(@"joypad activated");
	// start animation
	// set state to active
	[broker setAlpha:0.3];
	[broker setState:[JTCActiveState alloc]];
}

- (void)deactivationTimerFired:(NSTimer*)theTimer { }

-(void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event {
	if( activationTimer != nil ) {
		[activationTimer invalidate];
		[activationTimer release];
		activationTimer = nil;
	}
}

-(void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event {}

-(void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event {
	if( activationTimer != nil ) {
		[activationTimer invalidate];
		[activationTimer release];
		activationTimer = nil;
	}
}

@end

@implementation JTCActiveState
@synthesize deactivationTimer;

-(id)init {
	if (self = [super init]) {
			deactivationTimer = nil;
	}
	return self;
}

-(void)dealloc {
	if( deactivationTimer != nil ) {
		[deactivationTimer invalidate];
		[deactivationTimer release];
		deactivationTimer = nil;
	}
	[super dealloc];
}

-(void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
	// if the touch starts then we cancel the time out.
	if( deactivationTimer != nil ) {
		[deactivationTimer invalidate];
		[deactivationTimer release];
		deactivationTimer = nil;
	}
}
	
-(void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event {
	if( deactivationTimer == nil ) {
		deactivationTimer = [[NSTimer scheduledTimerWithTimeInterval:DEACTIVATION_TIME
															target:broker selector:@selector(deactivationTimerFired:)
														userInfo:nil repeats:NO] retain];
	}
}

- (void)activationTimerFired:(NSTimer*)theTimer { }
	
- (void)deactivationTimerFired:(NSTimer*)theTimer {
	NSLog(@"joypad deactivated");
	[broker setAlpha:0.0];
	[deactivationTimer release];
	deactivationTimer = nil;
	// start animation
	// set state to inactive
	[broker setState:[JTCInactiveState alloc]];
}
	
-(void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event {
	NSLog(@"joypad touches moved");
	
	UITouch *touch = [touches anyObject];
	CGPoint t = [touch locationInView:broker];

	NSLog(@" touch (%f, %f)", t.x, t.y);
	
	[broker setXValue:t.x];
	[broker setYValue:t.y];
	[broker setRedrawRect:CGRectUnion([broker redrawRect], CGRectMake(t.x-5, t.y-5, 10, 10))];
	[broker setNeedsDisplayInRect:[broker redrawRect]];
}

-(void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event {
		// cancel robot movement! All stop!
		if( deactivationTimer != nil ) {
			[deactivationTimer invalidate];
			[deactivationTimer release];
			deactivationTimer = nil;
		}
}

@end


